package com.starview.star.code.repository;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

import com.starview.platform.data.value.ResourceURI;
import com.starview.platform.resource.catalog.CatalogException;
import com.starview.star.compiler.ErrorReport;
import com.starview.star.compiler.util.PrettyPrintDisplay;
import com.starview.star.compiler.util.PrettyPrintable;

/**
 * A CodeRepository should contain all the code of a project. It is not set up as a singleton; but
 * should be treated as such.
 * 
 * 
 * 
 * @author fgm
 * 
 */
@SuppressWarnings("serial")
public class CodeRepositoryImpl extends AbstractCodeRepository implements PrettyPrintable
{
  private final Map<ResourceURI, RepositoryNode> nodes = new HashMap<ResourceURI, RepositoryNode>();
  private final RepositoryNode generics = new RepositoryNodeImpl(ResourceURI.noUriEnum, null, new CodeMemory());

  public CodeRepositoryImpl(ClassLoader loader, boolean isSolo,ErrorReport errors)
  {
    super(loader, errors);
    if (isSolo)
      setupStarLib();
  }

  @Override
  public RepositoryNode addRepositoryNode(ResourceURI uri, String hash, CodeCatalog code) throws RepositoryException
  {
    RepositoryNode node = new RepositoryNodeImpl(uri, hash, code);
    mergeStdTypes(code);
    nodes.put(uri, node);
    triggerUpdates(node);
    return node;
  }

  @Override
  public void removeRepositoryNode(ResourceURI uri) throws CatalogException
  {
    RepositoryNode node = findNode(uri);
    if (node != null) {
      if (triggerDelete(node))
        nodes.remove(uri);
    }
  }

  @Override
  public RepositoryNode findNode(ResourceURI uri)
  {
    return nodes.get(uri);
  }

  @Override
  public RepositoryNode genericCode()
  {
    return generics;
  }

  @Override
  public Iterator<RepositoryNode> iterator()
  {
    return nodes.values().iterator();
  }

  @Override
  public void prettyPrint(PrettyPrintDisplay disp)
  {
    int mark = disp.markIndent(2);
    disp.append("{\n");
    for (Entry<ResourceURI, RepositoryNode> entry : nodes.entrySet()) {
      entry.getKey().prettyPrint(disp);
      disp.append(":");
      entry.getValue().prettyPrint(disp);
      disp.append("\n");
    }
    disp.popIndent(mark);
    disp.append("}");
  }

  @Override
  public String toString()
  {
    return PrettyPrintDisplay.toString(this);
  }
}
